/*
 * Copyright 2008. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the Apache License, Version 2.0. You
 * can find a copy of the license at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */

package com.sinai.mshab.extensions.search;

import java.util.ArrayList;

import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.sinai.mshab.format.ClonableWidget;
import com.sinai.mshab.format.Direction;
import com.sinai.mshab.format.FormatPanel;
import com.sinai.mshab.format.util.Observable;
import com.sinai.mshab.format.util.Observer;

/**
 * Condition field specifies a condition on a database field used for search.
 * Based on the type of the field selected, different operators will be
 * available.
 * 
 * @author serge
 * 
 */
public class SearchField extends FormatPanel implements ClonableWidget,
		Observable {

	public static final String CREATED_STATE = "CREATED_STATE";
	public static final String DESTROYED_STATE = "DESTROYED_STATE";

	private ListBox fields, operator;
	private TextBox value;
	private String table;
	private DatabaseStructure structure;
	private HorizontalPanel panel;
	private ArrayList observers = new ArrayList();
	private String state;

	/**
	 * Creates a new condition field
	 * 
	 * @param structure
	 * @param table
	 */
	public SearchField(DatabaseStructure structure, String table) {

		// save our values
		this.table = table;
		this.structure = structure;

		// set up the panel.
		this.setStyleName("mshab-SearchField");
		setDefaultLabelPosition(Direction.LEFT);
		setDefaultLeftLabelWidth(80);

		// make a list of fields for given table
		fields = new ListBox();
		ArrayList<Field> field_list = structure.getFields(table);
		for (int i = 0; i < field_list.size(); i++) {
			fields.addItem(field_list.get(i).getName());
		}

		// fields need to listen to changes to change the operator accordingly
		fields.addChangeListener(new FieldChangeListener());

		// make an hpanel to fit everything.
		panel = new HorizontalPanel();
		add(panel);

		// add an observer
		addObserver(SortByWidget.getInstance());

		// append operator and value to the panel.
		setUpOperatorAndValue();
	}

	/**
	 * Figures out which operator and value should be set based on the type of
	 * the field.
	 */
	private void setUpOperatorAndValue() {

		// clear this current panel
		panel.clear();

		// add the list again
		panel.add(fields);

		// figure out the type.
		String type = structure.getType(table, getField());

		// figure out which set of operators we need based on type
		if (type.equals("varchar")) {
			operator = new TextOperators();
		} else if (type.equals("int")) {
			operator = new IntOperators();
		} else if (type.equals("date")) {
			operator = new DateOperators();
		}
		panel.add(operator);

		// figure out the value to put in.
		if (type.equals("varchar")) {
			value = new TextBox();
		}
		panel.add(value);

		// notify the world of our existance
		state = CREATED_STATE;
		notifyObservers();
	}

	public String getField() {
		return fields.getValue(fields.getSelectedIndex());
	}

	public String getOperator() {
		return operator.getValue(operator.getSelectedIndex());
	}

	public Widget cloneWidget() {
		return new SearchField(structure, table);
	}

	private class FieldChangeListener implements ChangeListener {
		public void onChange(Widget sender) {
			state = DESTROYED_STATE;
			notifyObservers();
			setUpOperatorAndValue();
		}
	}

	public void addObserver(Observer o) {
		observers.add(o);
	}

	public void notifyObservers() {
		for (int i = 0; i < observers.size(); i++) {
			((Observer) observers.get(i)).update(this, state);
		}
	}

	public int countObservers() {
		return observers.size();
	}

	public void deleteObserver(Observer observer) {
		observers.remove(observer);
	}

	public void deleteObservers() {
		observers.clear();
	}

	public String getTableName() {
		return table;
	}

	/**
	 * Returns the field this condition was pointing to before any changes
	 * occured
	 * 
	 * @return
	 */
	public String getValue() {
		return value.getText();
	}
}
